home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
-
- Printing.c
-
- This file contains the printing code for the QuickDraw GX aware
- sample, "Simple Sample GX."
-
- Additional info can be found in the related develop #19 article,
- "Adding QuickDraw GX Printing to QuickDraw Applications."
-
- Dave Hersey, Apple Developer Technical Support.
-
- ——————— Edit Trail ———————
-
- coughed up: 1/22/94 - dmh
- cleaned up for 2nd draft of develop article: 3/10/94 - dmh
- cleaned up for final: 4/14/94 - dmh
- build descriptors for ppc 8/17/94 - nick
-
- *********************************************************************/
-
- #include "Simple Sample.h"
-
-
- /************************************************************
- MyPrintDocument - This routine displays the QuickDraw GX
- or non-QuickDraw GX "Print" dialog, and then prints the
- document.
-
- *************************************************************/
-
- OSErr MyPrintDocument(MyDocumentPtr whichDocument)
- {
- OSErr err = noErr;
- gxEditMenuRecord editMenuRec;
- gxDialogResult result;
-
- if (gGXIsPresent)
- {
- /*
- If QuickDraw GX is present, fill in the location of the application's
- Edit menu items, enable/disable appropriate menu items, and display
- the Print dialog. If the user clicks the Print button, print using
- QuickDraw GX.
- */
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = iCut;
- editMenuRec.copyItem = iCopy;
- editMenuRec.pasteItem = iPaste;
- editMenuRec.clearItem = iClear;
- editMenuRec.undoItem = iUndo;
-
- MyAdjustMenusForPrintDialogs(true);
- result = GXJobPrintDialog(whichDocument->documentJob, &editMenuRec);
- MyAdjustMenusForPrintDialogs(false);
-
- if (result == gxOKSelected)
- err = MyGXPrintLoop(whichDocument);
- }
- else
- {
- /*
- If QuickDraw GX is NOT present, open the printer driver, and put up the
- old Print dialog. If the user clicks the Print button, print using
- the Printing Manager.
- */
- PrOpen();
- PrValidate(whichDocument->documentPrintHdl);
- if (PrJobDialog(whichDocument->documentPrintHdl))
- err = MyQDPrintLoop(whichDocument); // Print using QuickDraw.
- PrClose();
- }
-
- return err;
- }
-
-
- /************************************************************
- MyPrintOneCopy - This routine sets up job collection items
- so that we'll print one copy of the passed document, then
- it jumps into our printing routine. This function is only
- called when QuickDraw GX is running.
-
- *************************************************************/
-
- OSErr MyPrintOneCopy(MyDocumentPtr whichDocument)
- {
- OSErr err;
- Collection jobCollection;
- gxCopiesInfo copiesInfo;
- gxFileDestinationInfo destInfo;
- gxPageRangeInfo pageRangeInfo;
- Ptr oldCopiesInfo = nil, oldPageRangeInfo = nil, oldDestInfo = nil;
- long oldCopiesSize, oldPageRangeInfoSize, oldDestInfoSize;
-
- // Get the job collection and set it up to print one copy…
-
- jobCollection = GXGetJobCollection(whichDocument->documentJob);
-
- // Set number of copies to 1.
-
- copiesInfo.copies = 1;
- err = MyReplaceCollectionItem(&copiesInfo, sizeof(gxCopiesInfo),
- gxCopiesTag, gxPrintingTagID,
- jobCollection, &oldCopiesInfo, &oldCopiesSize);
- nrequire(err, ReplaceCopies_error);
-
- // Set page range to "all".
-
- pageRangeInfo.simpleRange.optionChosen = gxDefaultPageRange;
- pageRangeInfo.minFromPage = 1;
- pageRangeInfo.simpleRange.fromPage = 1;
- pageRangeInfo.maxToPage = whichDocument->numPages;
- pageRangeInfo.simpleRange.toPage = whichDocument->numPages;
- pageRangeInfo.simpleRange.printAll = true;
- err = MyReplaceCollectionItem(&pageRangeInfo, sizeof(gxPageRangeInfo),
- gxPageRangeTag, gxPrintingTagID,
- jobCollection, &oldPageRangeInfo, &oldPageRangeInfoSize);
- nrequire(err, ReplacePageRange_error);
-
- // Set destination to "printer".
-
- destInfo.toFile = false;
- err = MyReplaceCollectionItem(&destInfo, sizeof(gxFileDestinationInfo),
- gxFileDestinationTag, gxPrintingTagID,
- jobCollection, &oldDestInfo, &oldDestInfoSize);
- nrequire(err, ReplaceDestination_error);
-
- // Print one copy of our document.
-
- err = MyGXPrintLoop(whichDocument);
-
- /*
- Restore original number of copies, page range, and output
- destination in case anybody uses that info.
- */
-
- ReplaceDestination_error:
- MyReplaceCollectionItem(oldDestInfo, oldDestInfoSize,
- gxFileDestinationTag, gxPrintingTagID,
- jobCollection, nil, nil);
- ReplacePageRange_error:
- MyReplaceCollectionItem(oldPageRangeInfo, oldPageRangeInfoSize,
- gxPageRangeTag, gxPrintingTagID,
- jobCollection, nil, nil);
- ReplaceCopies_error:
- MyReplaceCollectionItem(oldCopiesInfo, oldCopiesSize,
- gxCopiesTag, gxPrintingTagID,
- jobCollection, nil, nil);
-
- // Dispose of the pointers that MyReplaceCollectionItem created.
-
- if (oldCopiesInfo)
- DisposePtr(oldCopiesInfo);
-
- if (oldPageRangeInfo)
- DisposePtr(oldPageRangeInfo);
-
- if (oldDestInfo)
- DisposePtr(oldDestInfo);
-
- return err;
- }
-
-
- /************************************************************
- MyQDPrintLoop - This is our non-QuickDraw GX printing
- routine.
-
- *************************************************************/
-
- OSErr MyQDPrintLoop(MyDocumentPtr whichDocument)
- {
- OSErr err = noErr;
- THPrint hPrint;
- TPPrPort printPort;
- TPrStatus theStatus;
- short copy, pg, iFstPage, iLstPage, oldCurPage;
-
- hPrint = whichDocument->documentPrintHdl;
- oldCurPage = whichDocument->curPage;
-
- iFstPage = (*hPrint)->prJob.iFstPage;
- if (iFstPage < 1)
- iFstPage = 1;
-
- iLstPage = (*hPrint)->prJob.iLstPage;
- if (iLstPage > whichDocument->numPages)
- iLstPage = whichDocument->numPages;
-
- (*hPrint)->prJob.iFstPage = 1;
- (*hPrint)->prJob.iLstPage = 9999;
-
- /*
- Loop for the number of copies we need to make, opening a
- document and a page for each.
- */
- for (copy = 1; !err && (copy <= (*hPrint)->prJob.iCopies); copy++)
- {
- printPort = PrOpenDoc(hPrint, nil, nil);
-
- if (!(err = PrError()))
- for (pg = iFstPage; pg <= iLstPage; pg++)
- {
- PrOpenPage(printPort, nil);
-
- whichDocument->curPage = pg;
- MyDrawContents(whichDocument->documentWindow);
-
- PrClosePage(printPort);
- }
-
- PrCloseDoc(printPort);
- }
-
- // When finished printing, call PrPicFile (if necessary).
-
- if (!err) err = PrError();
-
- if (!err && ((*hPrint)->prJob.bJDocLoop == bSpoolLoop))
- PrPicFile(hPrint, nil, nil, nil, &theStatus);
-
- whichDocument->curPage = oldCurPage;
-
- return err;
- }
-
-
- /************************************************************
- MyGXPrintLoop - This is our QuickDraw GX printing
- routine.
-
- *************************************************************/
-
- OSErr MyGXPrintLoop(MyDocumentPtr whichDocument)
- {
- OSErr err;
- long firstPage, lastPage, numPages, pg;
- long oldPage;
- gxViewPort printViewPort;
- Point patStretch = {1,1};
- gxFormat pageFormat;
- Rect everywhereRect;
- MySpoolDataRec spoolData;
-
- oldPage = whichDocument->curPage;
-
- /*
- Determine which pages the user selected to print. If
- the user specifies a page range that is greater than
- the actual number of pages in the document, only print
- those pages that are actually in the document.
- */
- GXGetJobPageRange(whichDocument->documentJob, &firstPage, &lastPage);
-
- if (lastPage > whichDocument->numPages)
- lastPage = whichDocument->numPages;
-
- /*
- Calculate the total number of pages to print, and begin
- printing if there are no errors.
- */
- numPages = lastPage - firstPage +1;
- err = GXGetJobError(whichDocument->documentJob);
- nrequire(err, PageRangeError);
-
- GXStartJob(whichDocument->documentJob, whichDocument->documentTitle, numPages);
- err = GXGetJobError(whichDocument->documentJob);
- nrequire(err, StartJobFailed);
-
- /*
- Create a new viewport for printing, and set our translator rects
- to "wide open" so they include all data we're drawing. For each
- page we print, call GXStartPage, draw, and call GXFinishPage.
- */
- SetRect(&everywhereRect, 0, 0, 32767, 32767);
- printViewPort = GXNewViewPort(gxScreenViewDevices);
-
- for (pg = firstPage; (err == noErr) && (pg <= lastPage); pg++)
- {
-
- // Get the page's format and start printing the page.
-
- pageFormat = whichDocument->pageFormat[pg -1];
-
- if (pageFormat == nil)
- pageFormat = GXGetJobFormat(whichDocument->documentJob, 1);
-
- GXStartPage(whichDocument->documentJob,
- pg,
- pageFormat,
- 1,
- &printViewPort);
-
- err = GXGetJobError(whichDocument->documentJob);
-
- /*
- If there were no errors, set up the Translator, draw the QuickDraw
- data for the current page and remove the Translator.
-
- Note that, although it looks like it takes a GrafPtr,
- GXInstallQDTranslator actually requires a pointer to a CGrafPort,
- and will crash if you pass it a true GrafPtr.
- */
- nrequire(err, StartPageFailed);
- spoolData.printViewPort = printViewPort;
- GXGetFormatDimensions(pageFormat, &spoolData.pageArea, nil);
-
- GXInstallQDTranslator(whichDocument->documentWindow,
- gxDefaultOptionsTranslation,
- &everywhereRect, &everywhereRect,
- patStretch,
- NewgxShapeSpoolProc(MyPrintAShape),
- &spoolData);
-
- whichDocument->curPage = pg;
- SetPort(whichDocument->documentWindow);
- MyDrawContents(whichDocument->documentWindow);
- GXRemoveQDTranslator(whichDocument->documentWindow, nil);
-
- // Finish the page.
-
- GXFinishPage(whichDocument->documentJob);
- }
-
- // Finish printing.
-
- StartPageFailed:
-
- GXFinishJob(whichDocument->documentJob);
- err = GXGetJobError(whichDocument->documentJob);
-
- GXDisposeViewPort(printViewPort);
- whichDocument->curPage = oldPage;
-
- StartJobFailed:
- PageRangeError:
- return err;
- }
-
-
- /************************************************************
- MyPrintAShape - This is a spool proc. for the translator
- routines. In this routine, we simply draw each shape
- we're passed (printing it). You could also capture each
- shape into one gxPicture shape, and then do one draw of
- that afterwards.
-
- *************************************************************/
-
- OSErr MyPrintAShape(gxShape currentShape, long refCon)
- {
- MySpoolDataPtr spoolData;
- gxShapeType theShapeType;
-
- /*
- Don't waste time spooling the shape if it's being
- drawn completely off the page.
- */
- spoolData = (MySpoolDataPtr) refCon;
- theShapeType = GXGetShapeType(currentShape);
-
- if ((theShapeType == gxEmptyType) ||
- (theShapeType == gxFullType) ||
- (theShapeType == gxPictureType) ||
- (GXTouchesBoundsShape(&spoolData->pageArea, currentShape)))
- {
- GXSetShapeViewPorts(currentShape, 1, &spoolData->printViewPort);
- GXDrawShape(currentShape);
- }
-
- return (OSErr) GXGetGraphicsError(nil);
- }
-
-
- /************************************************************
- MyDoPageSetup - This routine handles the "Page Setup"
- dialog for QuickDraw GX and non-QuickDraw GX environments.
-
- *************************************************************/
-
- Boolean MyDoPageSetup(MyDocumentPtr whichDocument)
- {
- Boolean result;
- gxDialogResult dlgResult;
- gxEditMenuRecord editMenuRec;
-
- if (gGXIsPresent) // QuickDraw GX is being used.
- {
- /*
- Fill in the location of the application’s Edit menu items
- and enable the appropriate menu items.
- */
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = iCut;
- editMenuRec.copyItem = iCopy;
- editMenuRec.pasteItem = iPaste;
- editMenuRec.clearItem = iClear;
- editMenuRec.undoItem = iUndo;
-
- MyAdjustMenusForPrintDialogs(true);
- dlgResult = GXJobDefaultFormatDialog(whichDocument->documentJob, &editMenuRec);
- MyAdjustMenusForPrintDialogs(false);
- result = (dlgResult == gxOKSelected);
- }
- else // QuickDraw GX is not being used.
- {
- PrOpen();
- PrValidate(whichDocument->documentPrintHdl);
- result = PrStlDialog(whichDocument->documentPrintHdl);
- PrClose();
- }
-
- return result;
- }
-
-
- /************************************************************
- MyDoCustomPageSetup - This routine handles the "Custom
- Page Setup" dialog for QuickDraw GX and is never called
- unless QuickDraw GX is being used.
-
- *************************************************************/
-
- Boolean MyDoCustomPageSetup(MyDocumentPtr whichDocument)
- {
- OSErr err = noErr;
- gxDialogResult result;
- gxEditMenuRecord editMenuRec;
- gxFormat pageFormat;
- Boolean newPgFormat = false;
-
- /*
- Fill in the location of the application’s Edit menu items
- and enable the appropriate menu items.
- */
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = iCut;
- editMenuRec.copyItem = iCopy;
- editMenuRec.pasteItem = iPaste;
- editMenuRec.clearItem = iClear;
- editMenuRec.undoItem = iUndo;
-
- MyAdjustMenusForPrintDialogs(true);
-
- /*
- If we have an existing page format, we'll modify that.
- Otherwise, we'll need to create a new format and use that.
- */
- if (whichDocument->pageFormat[whichDocument->curPage -1] != nil)
- pageFormat = whichDocument->pageFormat[whichDocument->curPage -1];
- else
- {
- pageFormat = GXNewFormat(whichDocument->documentJob);
- newPgFormat = true;
- err = GXGetJobError(whichDocument->documentJob);
- }
-
- // If no errors, display the format dialog.
-
- if (err == noErr)
- {
- result = GXFormatDialog(pageFormat, &editMenuRec, nil);
-
- switch (result)
- {
-
- /*
- If the user selected "Remove", use the default job format
- with this page. For our application, we indicate this by
- storing nil for the format reference in our structure.
-
- If "OK" was selected, store the new format with this page.
- */
- case gxRevertSelected:
- GXDisposeFormat(pageFormat);
- pageFormat = nil;
-
- case gxOKSelected:
- whichDocument->pageFormat[whichDocument->curPage -1] = pageFormat;
- break;
-
- /*
- If the user selected "Cancel", dispose of our cloned copy
- of the default job format, if we made one.
- */
- case gxCancelSelected:
- if (newPgFormat) GXDisposeFormat(pageFormat);
- break;
- }
- }
-
- MyAdjustMenusForPrintDialogs(false);
-
- return newPgFormat;
- }
-
-
- /************************************************************
- MyRepaginateDoc - This routine handles repagination of our
- document.
-
- *************************************************************/
-
- void MyRepaginateDoc(MyDocumentPtr whichDocument)
- {
- long pageNum;
- Rect repaginateRect;
- gxRectangle pageArea, paperArea;
- gxFormat pageFormat;
-
- for (pageNum = 1; pageNum <= whichDocument->numPages; pageNum++)
- {
-
- /*
- Repaginate our document using the format's page area
- if QuickDraw GX is being used, or else the print
- record's rPage.
- */
- if (gGXIsPresent) // QuickDraw GX is being used.
- {
- pageFormat = whichDocument->pageFormat[pageNum -1];
-
- if (pageFormat == nil)
- pageFormat = GXGetJobFormat(whichDocument->documentJob, 1);
-
- GXGetFormatDimensions(pageFormat, &pageArea, &paperArea);
-
- SetRect(&repaginateRect,
- pageArea.left >>16,
- pageArea.top >>16,
- pageArea.right >>16,
- pageArea.bottom >>16);
- }
- else // QuickDraw GX isn't being used.
- repaginateRect = (*whichDocument->documentPrintHdl)->prInfo.rPage;
-
- /*
- Repaginate the document based on our printable area.
- .
- .
- .
- */
-
- }
- }
-
-
- /************************************************************
- MyReplaceCollectionItem - This routine replaces a
- collection item with the passed data. If the oldData
- pointer is not nil, the data that's being replaced is
- returned in it. (If the item doesn't already exist, then
- a copy of the newData is returned instead.) Note that the
- oldData pointer is actually created in this routine. You
- just pass a pointer indicating where to store it (or nil
- if you don't want the old data returned).
-
- *************************************************************/
-
- OSErr MyReplaceCollectionItem(void *newData, long collectSize,
- OSType collectType, long collectID,
- Collection whichCollection,
- Ptr *oldData, long *oldDataSize)
- {
- OSErr err;
- long index;
-
- /*
- If we're supposed to return the old data, get it.
- If there is no old data, return a copy of the new data.
- */
- if (oldData)
- {
- err = GetCollectionItemInfo(whichCollection,
- collectType,
- collectID,
- dontWantIndex,
- oldDataSize,
- dontWantAttributes);
- if (err)
- {
- *oldDataSize = collectSize;
- *oldData = NewPtrSys(*oldDataSize);
- if (!(err = MemError()))
- BlockMove(newData, *oldData, collectSize);
- }
- else
- {
- *oldData = NewPtrSys(*oldDataSize);
- if (!(err = MemError()))
- err = GetCollectionItem(whichCollection,
- collectType,
- collectID,
- dontWantSize,
- *oldData);
- }
-
- nrequire(err, CouldNotSetOldData);
- }
-
- /*
- If we're adding a new collection item, do so. Otherwise,
- get the existing item's index and replace the old collection
- item.
- */
- err = AddCollectionItem(whichCollection,
- collectType,
- collectID,
- collectSize,
- newData);
-
- if (err == collectionItemLockedErr)
- {
- err = GetCollectionItemInfo(whichCollection,
- collectType,
- collectID,
- &index,
- dontWantSize,
- dontWantAttributes);
- if (!err)
- err = ReplaceIndexedCollectionItem(whichCollection,
- index,
- collectSize,
- newData);
- }
-
- CouldNotSetOldData:
- return err;
- }
-